#[macro_use]
extern crate glium;

#[path = "tuto-07-teapot.rs"]
mod teapot;

pub const PI: f32 = 3.141592;

struct Point
{
    x: i32,
    y: i32,
}

//绕水平轴旋转，这个是绕物体自身的坐标轴旋转
#[allow(dead_code)]
pub fn view_hori(n: f32) -> [[f32; 4]; 4]
{
    let a = -n;
    [
        [1.0, 0.0, 0.0, 0.0],
        [0.0, a.cos(), a.sin(), 0.0],
        [0.0, -a.sin(), a.cos(), 0.0],
        [0.0, 0.0, 0.0, 1.0],
    ]
}

//绕垂直轴旋转，物体自身的坐标轴
#[allow(dead_code)]
pub fn view_vert(n: f32) -> [[f32; 4]; 4]
{
    let a = -n;
    [
        [a.cos(), 0.0, -a.sin(), 0.0],
        [0.0, 1.0, 0.0, 0.0],
        [a.sin(), 0.0, a.cos(), 0.0],
        [0.0, 0.0, 0.0, 1.0],
    ]
}

fn main()
{
    use glium::{DisplayBuild, Surface};
    let display = glium::glutin::WindowBuilder::new().with_depth_buffer(24).build_glium().unwrap();

    let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap();
    let normals = glium::VertexBuffer::new(&display, &teapot::NORMALS).unwrap();
    let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList,
                                          &teapot::INDICES).unwrap();

    let vertex_shader_src = r#"
        #version 140

        in vec3 position;
        in vec3 normal;

        uniform mat4 matrix;
        uniform mat4 matrix_hori;
        uniform mat4 matrix_vert;

        void main() {
            gl_Position = matrix*matrix_hori*matrix_vert*vec4(position, 1.0);
        }
    "#;

    let fragment_shader_src = r#"
        #version 140

        out vec4 color;

        void main() {
            color = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "#;

    let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src,
                                              None).unwrap();
    let draw_params = glium::DrawParameters
    {
        depth: glium::Depth
        {
            test: glium::draw_parameters::DepthTest::IfLess,
            write: true,
            .. Default::default()
        },
        polygon_mode: glium::PolygonMode::Line,//Line:画线框 Fill:填充
        backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise,
        ..Default::default()
    };

    let mut point = Point{x: 0, y: 0};

    let mut matrix_hori = [
        [1.0, 0.0, 0.0, 0.0],
        [0.0, 1.0, 0.0, 0.0],
        [0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 1.0f32]
    ];
    let mut matrix_vert = [
        [1.0, 0.0, 0.0, 0.0],
        [0.0, 1.0, 0.0, 0.0],
        [0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 1.0f32]
    ];

    //缩放矩阵，x y 各缩小10倍
    let matrix = [
        [0.01, 0.0, 0.0, 0.0],
        [0.0, 0.01, 0.0, 0.0],
        [0.0, 0.0, 0.01, 0.0],
        [0.0, 0.0, 0.0, 1.0f32]
    ];

    let mut mouse_move = false;

    let mut t_x = 0.0f32;
    let mut t_y = 0.0f32;

    let mut angle = 0.0f32;
    loop
    {
        let mut target = display.draw();
        //target.clear_color(0.0, 0.0, 1.0, 1.0);
        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        angle = angle + 0.001*PI;
        if angle > PI
        {
            angle = angle - PI;
        }


        let uniform = uniform! {matrix: matrix, matrix_hori: matrix_hori, matrix_vert: matrix_vert };

        target.draw((&positions, &normals), &indices, &program, &uniform,&draw_params).unwrap();
        target.finish().unwrap();

        for ev in display.poll_events()
        {
            match ev
            {
                glium::glutin::Event::Closed => return,
                glium::glutin::Event::MouseInput(state, button) =>
                {
                    if glium::glutin::MouseButton::Right == button
                    {
                        if glium::glutin::ElementState::Pressed == state
                        {
                            println!("{:?}", state);
                            mouse_move = true;
                        }
                        else
                        {
                            mouse_move = false;
                        }
                    }
                },
                glium::glutin::Event::MouseMoved(x, y) =>
                {
                    if mouse_move
                    {
                        println!("x: {}, y: {}", x, y);
                        if x - point.x > 0
                        {
                            t_x = t_x + 0.01;
                            matrix_vert = view_hori(t_x);
                        }
                        else if x - point.x < 0
                        {
                            t_x = t_x - 0.01;
                            matrix_vert = view_hori(t_x);
                        }

                        if y - point.y > 0
                        {
                            t_y = t_y + 0.01;
                            matrix_hori = view_vert(t_y);
                        }
                        else if y - point.y < 0
                        {
                            t_y = t_y - 0.01;
                            matrix_hori = view_vert(t_y);
                        }
                        // println!("{:?}", matrix_vert);
                        point.x = x;
                        point.y = y;
                    }
                },
                _ => ()
            }
        }
    }
}
